<script setup>
import { ref, onMounted } from "vue";
import { ElMessage } from "element-plus";
import storeWs from "@/utils/store-ws";
import { useStore } from "vuex";
import Dexie from "dexie";
import request from "@/utils/request";
import { useRouter } from "vue-router";
const router = useRouter();

const store = useStore();
const userList = ref();
// 联系人
const contacts = ref("");
const news = ref("");
// 创建消息数据库
var db = new Dexie(`${store.state.userInfo.username}`);
db.version(1).stores({
  users: "++id, username, message, sender",
  userList: "username,name,avatar",
});

// 添加消息 sender为0：右边展示 dender为1：左边展示
const addChat = (username, message, sender) => {
  db.users.add({
    username,
    message,
    createdAt: new Date(),
    sender,
  });
};

//登录获取消息
const getChatList = async () => {
  const res = await request.get(`/chat/list/${store.state.userInfo.username}`);
  res.data.forEach((item) => {
    db.userList.add({
      username: item.myUsername,
      name: item.name,
      avatar: item.avatar,
    });
    addChat(item.myUsername, item.message, 1);
  });
  // 获取 userList 表的引用, 使用 toArray() 方法检索所有记录，并返回一个 Promise
  db.table("userList")
    .toArray()
    .then((users) => {
      userList.value = users;
    });
};

//发送消息
const sendMessage = (message) => {
  if (!message) {
    ElMessage({
      message: "发送内容不能为空",
      type: "warning",
    });
  } else {
    chatData.value.unshift({ message: message, sender: 0 });
    addChat(contacts.value, message, 0);
    ws.send(
      createMessage(
        contacts.value,
        news.value,
        store.state.userInfo.name,
        store.state.userInfo.avatar
      )
    );
    news.value = "";
  }
};

// 创建聊天框,没有则添加数据库
storeWs.subscribe((username, name, avatar) => {
  contacts.value = username;
  db.userList.add({
    username,
    name,
    avatar,
  });
  db.table("userList")
    .toArray()
    .then((users) => {
      userList.value = users;
    });
});

// 修改联系人,获取聊天记录
const changeContacts = (username) => {
  if (contacts.value == username) {
    contacts.value = "";
  } else {
    contacts.value = username;
    fetchUserData(username);
  }
};

// 查询消息
var chatData = ref([]);
const fetchUserData = async (username) => {
  try {
    let allUsers = await db.users.where("username").equals(username).toArray();
    // 如果需要保留原数组不变，则先复制数组
    let reversedUsers = allUsers.slice().reverse();
    // 取前20条记录（如果数组长度小于20，则取全部）
    chatData.value = reversedUsers.slice(0, 20);
    // 查找到的聊天记录
    // console.log(chatData.value);
  } catch (error) {
    console.error("查询失败", error);
  }
};

const ws = new WebSocket(`ws://localhost:8081?token=${localStorage.getItem("token")}`);
// 监听WebSocket的打开事件
// ws.onopen = () => {
//   console.log("WebSocket 链接已打开");
// };
ws.onmessage = (msgObj) => {
  //接收到的消息
  // console.log(JSON.parse(msgObj.data));
  const { username, message, avatar, name } = JSON.parse(msgObj.data);
  if (contacts.value == username) {
    chatData.value.unshift({ message: message, sender: 1 });
  }
  db.userList.add({
    username,
    name,
    avatar,
  });
  addChat(username, message, 1);
  db.table("userList")
    .toArray()
    .then((users) => {
      userList.value = users;
    });
};
onMounted(() => {
  getChatList();
});

function createMessage(toUsername, message, name, avatar) {
  return JSON.stringify({
    name,
    avatar,
    toUsername,
    message,
  });
}

const toCenter = (username) => {
  if (contacts.value == username) {
    router.push(`/personal/${username}`);
  }
};
</script>
<template>
  <el-drawer
    direction="ltr"
    v-model="store.state.isShowChat"
    :with-header="false"
    size="30%"
  >
    <div class="main">
      <div v-for="item in userList" class="contacts" :key="item.username">
        <div class="top" @click="changeContacts(item.username)">
          <el-avatar
            v-if="contacts == item.username"
            @click.stop="toCenter(item.username)"
            :src="`http://localhost:3000/${item.avatar}`"
          />
          <el-avatar
            v-else
            :src="`http://localhost:3000/${item.avatar}`"
          />
          <div class="username">{{ item.name }}</div>
        </div>
        <div class="content" v-if="contacts == item.username">
          <div class="newsBox">
            <div v-for="(item, index) in chatData" :key="index" class="newsList">
              <!-- sender为0：发送者 dender为1：接收者 -->
              <div :class="['newsStyle', item.sender == 0 ? 'newsRight' : 'newsLeft']">
                {{ item.message }}
              </div>
            </div>
          </div>
          <div class="bottom">
            <el-input
              v-model="news"
              style="width: 100%; height: 40px"
              placeholder="请输入内容"
              @keyup.enter="sendMessage(news)"
            >
            </el-input>
          </div>
        </div>
      </div>
    </div>
  </el-drawer>
</template>

<style lang="scss">
.el-drawer {
  min-width: 400px;
}
.main {
  height: 100%;
  overflow: hidden;
  overflow-y: scroll;
  .contacts {
    border: 1px solid gray;
    border-radius: 10px;
    box-sizing: border-box;
    padding: 0 10px;
    margin-bottom: 5px;
    .top {
      align-items: center;
      height: 50px;
      line-height: 50px;
      display: flex;
      cursor: default;
      .username {
        padding-left: 8px;
        font-size: 14px;
        font-weight: 600;
        color: rgb(58, 56, 56);
        line-height: 50px;
      }
    }
    .content {
      position: relative;
      overflow-y: auto;
      padding-bottom: 10px;
      .newsBox {
        display: flex;
        flex-direction: column-reverse;
        height: 400px;
        margin-bottom: 15px;
        overflow-y: scroll;
        .news-right {
          float: right;
        }
      }
    }
  }
}
.newsList {
  .newsStyle {
    box-sizing: border-box;
    max-width: 90%;
    clear: both;
    line-height: 30px;
    border-radius: 5px;
    padding: 5px 15px;
    margin: 5px 0;
  }
  .newsLeft {
    float: left;
    background-color: #f2f2f4;
    text-align: left;
  }
  .newsRight {
    float: right;
    background-color: #ffe40e;
    text-align: left;
  }
}
</style>
